unit SearchFile;

interface

uses
  Classes, Contnrs, SysUtils;

  type
    TSearchFileType = (fa_Directory, fa_File, fa_All );

    TSearchFileData = class
      Filename:string;
      FileSize:Int64;
      isFolder: Boolean;
      constructor Create(aFileName:String; aFileSize:Int64; aisFolder:Boolean);
    end;

    TSearchFile = class
      private
        FLIst: TObjectList;
        FExcludeAttribute: integer;
        FSearchFileType: TSearchFileType;
        FFileAttribute: Integer;
        function GetCount: Integer;
        procedure SetSearchFileType(const Value: TSearchFileType);
        procedure FileSearch(const PathName, FileName : string; const InDir : boolean);
        function IsFile(Fa:Integer): Boolean;
        function isFolder(Fa:Integer): Boolean;
        function GetFileData(index: Integer): TSearchFileData;
      public
        constructor Create;
        destructor Destroy; override;
        procedure Execute(StartFolder:string; FileMask:string; IncludeSubFolder:Boolean=False);

        property SearchFileType: TSearchFileType read FSearchFileType write SetSearchFileType;
        property Files[index:Integer]:TSearchFileData read GetFileData;
        property Count: Integer read GetCount;
        property ExcludeAttribute: integer read FExcludeAttribute Write FExcludeAttribute;
    end;

implementation

{ TSearchFile }

constructor TSearchFile.Create;
begin
  FLIst := TObjectList.Create(True);
  SearchFileType := fa_All;
  FExcludeAttribute := -1; 
end;

destructor TSearchFile.Destroy;
begin
  FList.Free;
  inherited;
end;

procedure TSearchFile.Execute(StartFolder:string; FileMask:string; IncludeSubFolder: Boolean);
begin
  Flist.Clear;
  FileSearch(StartFolder, FileMask, IncludeSubFolder);  
end;

procedure TSearchFile.FileSearch(const PathName, FileName: string;
  const InDir: boolean);
var Rec  : TSearchRec;
    Path : string;
begin
Path := IncludeTrailingBackslash(PathName);
if FindFirst(Path + FileName, faAnyFile , Rec) = 0 then
 try
   repeat
     case FSearchFileType of
       fa_Directory:
        begin
          if isFolder(Rec.Attr) then begin
            if (Rec.Name<>'.') and (Rec.Name<>'..') then begin
              if FExcludeAttribute = -1 then
                FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, True) )
              else if not (Rec.Attr and FExcludeAttribute <> 0) then
                FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, True) );
            end;
          end;
        end;
       fa_File:
        begin
          if isFile(Rec.Attr) then begin
            if (Rec.Name<>'.') and (Rec.Name<>'..') then begin
              if FExcludeAttribute = -1 then
                FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, False) )
              else if not (Rec.Attr and FExcludeAttribute <> 0) then
              FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, False) );
            end;
          end;
        end;
       fa_All:
        begin
          if (Rec.Name<>'.') and (Rec.Name<>'..') then  begin
            if (Rec.Attr and faDirectory) <> 0 then begin
              if FExcludeAttribute = -1 then
                FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, True) )
              else if not (Rec.Attr and FExcludeAttribute <> 0) then
                FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, True) );
            end
            else begin
              if FExcludeAttribute = -1 then
                FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, False) )
              else if not (Rec.Attr and FExcludeAttribute <> 0) then
                FList.Add( TSearchFileData.Create(Path + Rec.Name, Rec.Size, False) );
            end;
          end;
        end;
     end;
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;

If not InDir then Exit;

if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
 try
   repeat
    if ((Rec.Attr and faDirectory) <> 0)  and (Rec.Name<>'.') and (Rec.Name<>'..') then
     FileSearch(Path + Rec.Name, FileName, True);
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;
end;

function TSearchFile.GetCount: Integer;
begin
  Result := FList.Count;
end;


function TSearchFile.GetFileData(index: Integer): TSearchFileData;
begin
  Result := TSearchFileData(FList.Items [ index ]);
end;

function TSearchFile.IsFile(Fa: Integer): Boolean;
begin
  if (Fa and faDirectory = 0) then Result := True
  else Result := False; 
end;

function TSearchFile.isFolder(Fa: Integer): Boolean;
begin
  if (Fa and faDirectory <> 0) then result := True
  else Result := False;
end;

procedure TSearchFile.SetSearchFileType(const Value: TSearchFileType);
begin
  FSearchFileType := Value;
  case FSearchFileType of
    fa_Directory: begin FFileAttribute := faDirectory; end;
    fa_File: begin FFileAttribute := faAnyFile; end;
    fa_All: begin FFileAttribute := faAnyFile; end;
  end;
end;

{ TFileRecord }

constructor TSearchFileData.Create(aFileName: String; aFileSize: Int64; aisFolder:Boolean);
begin
  Filename := aFileName;
  FileSize := aFileSize;
  isFolder := aisFolder;
end;

end.
